import { _pick, _omit, canUse, isUndefined, randomString } from "mmb";
import { AppCTX } from "../../types/koaExtend";
import { encode } from "../../utils/jwt";
import pageMW from "../../middleware/pager";
import { sendVerifyCode, verifyCode } from "../../proxy/gsmsProxy";
import {
  getSessionByCode,
  decryptMobile,
  createQR,
} from "../../service/wechatService";
import { getUploadToken as getQiniuUploadToken } from "../../service/qiniuService";
import { getAuthorization } from "../../service/cosService";
import {
  createUser,
  getUserByOpenID,
  getUserWithStat,
  UpdateMobile,
  updateMemberToken,
  UpdateInfo,
  UpsertExt,
  createUserAccountWithdrawApplyment,
  listUserAccountWithdrawApplyments,
  getUserAccount,
  listUserAccountLogs,
  aggrUserAccountLogsToInOut,
  getUser,
} from "../../service/userService";
import { isSearchTerm } from "../../bg-enums/searchTerm";
import { User } from "../../service/declareTypes";
import {
  createUserPvLog,
  createUserPvLogMq,
} from "../../service/userPvLogService";
import { upsertUserFan, upsertUserFanMq } from "../../service/userFanService";
import {
  upsertUserFollow,
  upsertUserFollowMq,
} from "../../service/userFollowService";
import { upsertBrandFanMq } from "../../service/brandFanService";
import { upsertBrandFollowMq } from "../../service/brandFollowService";
import { upsertStoreFanMq } from "../../service/storeFanService";
import { upsertStoreFollowMq } from "../../service/storeFollowService";
import { checkMobile, register, credibleLogin } from "../../proxy/accountProxy";
import { createActivityUserPvLogMq } from "../../service/activityUserPvLogService";
import LandingPage, { isLandingPage } from "../../bg-enums/landingPage";
import { isWithdrawTarget } from "../../bg-enums/withdrawTarget";
import { listSearchObjectsAsSpokesman } from "../../service/commonService";
import Router from "koa-router";
const router = new Router();

// 识别用户
router.post("/usr/user/identify", async (ctx: AppCTX, next) => {
  // a-代表建立follow关系的用户id, b-代表信息分享人id
  const { code, a, b, brandId, storeId } = ctx.request.body;
  let { openId, page, activityId } = ctx.request.body;
  if (isUndefined(page)) {
    page = LandingPage.OTHER;
  }

  if (!isLandingPage(page)) {
    ctx.throw(400, "invalid page");
  }
  let user: User | undefined = undefined;

  // let sessionKey: string | undefined = undefined

  // todo: 调整顺序
  if (!isUndefined(openId)) {
    // 检查是否存在user
    // 理论上openId存在, 但是可能会有各种异常
    user = await getUserByOpenID(openId);
  }

  if (isUndefined(user) || isUndefined(openId)) {
    // 没定义openId, 通过code换取openId,并
    console.log("getSessionByCode:");
    const session = await getSessionByCode(code);
    console.log(" get session", session);
    openId = session.openId;

    user = await createUser({
      openId,
      nickName: `游客10${randomString(10)}`,
      registerPage: page,
      unionId: session.unionId,
    });
    if (!isUndefined(b)) {
      // 更新userext.sharer
      const userExt = await UpsertExt({
        userId: user.userId,
        shareUserId: b,
      });

      console.log("userExt=>", userExt);

      // // 存在share, 将当前user作为sharer的粉丝
      // // 非阻塞执行
      // const userFan = await upsertUserFan({
      //   userId: a,
      //   followerUserId: user.userId,
      //   beFollowed: Date.now(),
      //   aliasName: user.nickName || ``, // 空字符串,前端判断显示匿名
      // });
      // console.log("userFan=>", userFan);

      // // 存在share, 将当前sharer作为当前user的关注的人
      // // 非阻塞执行
      // const userFollow = await upsertUserFollow({
      //   userId: user.userId,
      //   followedUserId: a,
      //   followed: Date.now(),
      // });
      // console.log("userFollow=>", userFollow);
    }
  }

  const userSafely = user!;

  const output = _pick(
    userSafely,
    "openId",
    "mobile",
    "pic",
    "nickName",
    "intro",
    "homepageBg"
  );
  const userId = userSafely.userId;

  // 加入user_pv_log 非阻塞执行
  createUserPvLogMq({ userId, brandId, shareUserId: b, page });

  if (!isUndefined(activityId)) {
    createActivityUserPvLogMq({ userId, activityId, shareUserId: b, page });
  }

  // 增加user的follow和fan关系
  if (canUse(a)) {
    console.log(
      `bgapi upsertUserFollowMq=>userId:${userId}, followedUserId:${a}`
    );
    upsertUserFollowMq({
      userId: user.userId,
      followedUserId: a,
      followed: Date.now(),
    });
    upsertUserFanMq({
      userId: a,
      followerUserId: user.userId,
      beFollowed: Date.now(),
      aliasName: user.nickName || `U${user.userId}`,
    });
  }

  // 增加brand的follow和fan关系
  if (canUse(brandId)) {
    upsertBrandFollowMq({
      userId: user.userId,
      followedBrandId: brandId,
      followed: Date.now(),
    });
    upsertBrandFanMq({
      brandId,
      followerUserId: user.userId,
      beFollowed: Date.now(),
      aliasName: user.nickName || `U${user.userId}`,
    });
  }

  // 增加store的follow和fan关系
  if (canUse(storeId)) {
    upsertStoreFollowMq({
      userId: user.userId,
      followedStoreId: storeId,
      followed: Date.now(),
    });
    upsertStoreFanMq({
      storeId,
      followerUserId: user.userId,
      beFollowed: Date.now(),
      aliasName: user.nickName || `U${user.userId}`,
    });
  }

  ctx.body = {
    apiToken: await encode({ userId, userOpenId: openId }),
    userId,
    ...output,
  };
});

// Obsolete生成七牛上传token next ver will remove
router.post("/usr/user/genQiniuUploadToken", async (ctx: AppCTX, next) => {
  const { bucket, expires } = ctx.request.body;
  const { userId } = ctx;
  const uToken = await getQiniuUploadToken({
    bucket,
    expires,
  });
  ctx.body = uToken;
});

// 生成Cos上传认证信息
router.get("/usr/user/getCosAuthorization", async (ctx: AppCTX, next) => {
  const { bucketPrefix } = ctx.request.query;
  const { userId } = ctx;
  if (!canUse(bucketPrefix)) {
    ctx.throw(400, "bucketPrefix不可用");
  }
  const authorization = await getAuthorization(bucketPrefix);
  ctx.body = authorization;
});

// 创建QR
router.post("/usr/user/createQR", async (ctx: AppCTX, next) => {
  const { page, scene, width, autoColor, lineColor, isHyaline } =
    ctx.request.body;
  const { userId } = ctx;
  const uri = await createQR({
    page,
    scene,
    width,
    autoColor,
    lineColor,
    isHyaline,
  });
  ctx.body = uri;
});

const messageTypeOfSendVerifyCode = `user-bind-mobile`;

// 生成手机验证码并发送
router.post("/usr/user/genMobileVerifyCode", async (ctx: AppCTX, next) => {
  const { mobile } = ctx.request.body;
  const { userId } = ctx;
  await sendVerifyCode({
    phone: mobile,
    messageType: messageTypeOfSendVerifyCode,
  });
  ctx.body = {
    userId,
    mobile,
  };
});

// 验证手机号(depressed)
// router.post("/usr/user/checkMobileVerifyCode", async (ctx: AppCTX, next) => {
//   const { mobile, vcode } = ctx.request.body;
//   const { userId } = ctx;
//   const isVerified = await verifyCode({
//     phone: mobile,
//     messageType: messageTypeOfSendVerifyCode,
//     code: vcode,
//   });
//   if (!isVerified) {
//     ctx.throw(400, "验证码错误");
//   }
//   ctx.body = {
//     userId,
//     mobile,
//     vcode,
//   };
// });

// 确保B端管理账号, 因为account系统仅接入B端用户,C端用户是用于BilinMember
const _ensureBilinAccount = async ({
  userId,
  mobile,
}: {
  userId: string;
  mobile: string;
}) => {
  let user = await UpdateMobile({ userId, mobile });

  // 1判断
  let isRegistered = await checkMobile(mobile);

  if (!isRegistered) {
    // 注册
    console.log(`准备注册手机:${mobile}`);
    isRegistered = await register(mobile);
  } else {
    console.log(`已注册手机:${mobile}`);
  }

  if (!isRegistered) {
    throw Error("无法注册mobile到账户中心");
  }
  const memberToken = await credibleLogin({ mobile, openId: user.openId });
  console.log("成功登录 memberToken=>", memberToken);
  if (memberToken) {
    user = await updateMemberToken({ userId, memberToken });
  }

  return {
    userId,
    mobile,
  };
};

// 绑定用户手机号码
router.put("/usr/user/bindMobile", async (ctx: AppCTX, next) => {
  const { userId } = ctx;
  const { mobile, vcode } = ctx.request.body;

  const isVerified = await verifyCode({
    phone: mobile,
    messageType: messageTypeOfSendVerifyCode,
    code: vcode,
  });
  if (!isVerified) {
    ctx.throw(400, "验证码错误");
  }
  let user = await UpdateMobile({ userId, mobile });
  // 暂时不在绑定手机确保BilinAccount
  // ctx.body = await _bindMobileForBilinAccount({ userId, mobile });
  ctx.body = {
    userId,
    mobile,
  };
});

// 绑定用户手机号码(加密)
router.put("/usr/user/bindMobileEncrypted", async (ctx: AppCTX, next) => {
  const { userId } = ctx;
  const { code, encryptedData, iv } = ctx.request.body;
  // 加密和不加密都有可能
  const { sessionKey } = await getSessionByCode(code);
  // const sessionKey = 'b5jiH+2H577zD10F5xvSzg=='
  console.log("sessionKey=>", sessionKey);
  console.log("encryptedData=>", encryptedData);
  console.log("iv=>", iv);
  let mobile = await decryptMobile({ sessionKey, encryptedData, iv });
  console.log("mobile=>", mobile);
  let user = await UpdateMobile({ userId, mobile });
  // 暂时不在绑定手机确保BilinAccount
  // ctx.body = await _ensureBilinAccount({ userId, mobile });
  ctx.body = {
    userId,
    mobile,
  };
});

// 更新用户基本信息
router.put("/usr/user/updateBaseInfo", async (ctx: AppCTX, next) => {
  const { userId } = ctx;
  const { pic, nickName, intro, homepageBg } = ctx.request.body;

  const user = await UpdateInfo({
    userId,
    pic,
    nickName,
    intro,
    homepageBg,
  });
  ctx.body = {
    ..._omit(user, "realName", "idCardNo"),
  };
});

// 获取个人敏感信息
router.get("/usr/user/sensitiveInfo", async (ctx: AppCTX, next) => {
  const { userId } = ctx;
  const user = await getUser(userId);
  const output = _pick(user, "realName", "idCardNo");

  // 之后考虑加密
  ctx.body = {
    ...output,
  };
});

//获取个人信息 适用于:首页,个人主页,我的
router.get("user-info", "/usr/user/:userId/info", async (ctx: AppCTX, next) => {
  const { userId } = ctx.params;
  const { page } = ctx.query;
  let body = {};
  const userWithStat = await getUserWithStat(userId);
  console.log("userWithStat=>", JSON.stringify(userWithStat));
  let output = {};
  if (page === "homepage") {
    output = _pick(
      userWithStat,
      "followUserCount",
      "followBrandCount",
      "involveActivityCount",
      "orderCount"
    );
  }
  if (page === "user-homepage") {
    output = _pick(
      userWithStat,
      "pic",
      "nickName",
      "intro",
      "homepageBg",
      "fansCount",
      "endorseActivityCount",
      "involveActivityCount"
    );
  }
  if (page === "my-index") {
    output = _pick(
      userWithStat,
      "nickName",
      "mobile",
      "fansCount",
      "endorseBrandCount",
      "endorseStoreCount"
    );
  }
  body = {
    userId,
    ...output,
  };
  ctx.body = body;
});

router.get("/usr/user/info", (ctx: AppCTX) => {
  const { userId } = ctx;
  const url = router.url("user-info", { userId }, { query: ctx.query });
  ctx.redirect(url);
  ctx.status = 301;
});

// 获取用户的账户
router.get("/usr/user/account", async (ctx: AppCTX, next) => {
  const { userId } = ctx;

  const userAccount = await getUserAccount(userId);
  ctx.body = userAccount;
});

// 个人申请提现
router.post("/usr/user/accountWithdrawApplyment", async (ctx: AppCTX, next) => {
  const { userId } = ctx;
  const { target, amount, realName, idCardNo, remark } = ctx.request.body;

  if (!isWithdrawTarget(target)) {
    ctx.throw(400, "invalid target");
  }

  const userAmountWithdrawApplyment = await createUserAccountWithdrawApplyment({
    userId,
    target,
    amount,
    realName,
    idCardNo,
    remark,
  });

  ctx.body = userAmountWithdrawApplyment;
});

// 获取用户的提现记录列表
router.get(
  "/usr/user/accountWithdrawApplyments",
  pageMW,
  async (ctx: AppCTX, next) => {
    const { userId, limit, offset } = ctx;
    const { total, items } = await listUserAccountWithdrawApplyments(userId, {
      limit,
      offset,
    });
    ctx.body = {
      total,
      rows: items,
    };
  }
);

// 获取用户的资金明细列表
router.get("/usr/user/accountLogs", pageMW, async (ctx: AppCTX, next) => {
  const { userId, limit, offset, ts } = ctx;
  const { begin, end } = ctx.request.query;

  const { total, items } = await listUserAccountLogs(
    userId,
    {
      begin: isUndefined(begin) ? 0 : parseInt(begin),
      end: isUndefined(end) ? Date.now() : parseInt(end),
    },
    {
      limit,
      offset,
      ts,
    }
  );
  ctx.body = {
    total,
    rows: items,
  };
});

// 统计用户的资金收入与支出
router.get(
  "/usr/user/aggrUserAccountLogsToInOut",
  async (ctx: AppCTX, next) => {
    const { userId } = ctx;
    const { begin, end } = ctx.request.query;

    const aggrRet = await aggrUserAccountLogsToInOut(userId, {
      begin: isUndefined(begin) ? 0 : parseInt(begin),
      end: isUndefined(end) ? Date.now() : parseInt(end),
    });

    ctx.body = aggrRet;
  }
);

// 获取用户查询使用的查询对象列表
router.get("/usr/user/searchObjects", pageMW, async (ctx: AppCTX, next) => {
  const { term, keyword } = ctx.query;
  const { userId, limit, offset } = ctx;

  if (!isSearchTerm(term)) {
    ctx.throw(400, "term invalid");
  }

  const { total, items } = await listSearchObjectsAsSpokesman(
    userId,
    term,
    keyword,
    {
      limit,
      offset,
    }
  );
  ctx.body = {
    total,
    rows: items,
  };
});

export default router;
